#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using starLiGHT.Input;
using System.Text;

#endregion

namespace starLiGHT.Sandbox.InputManager
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        starLiGHT.Input.InputManager inputManager;

        String deviceDebug;

        Texture2D mouseTexture;
        Texture2D buttonTexture;
        Texture2D gamePadFront; RectangleF gamePadFrontHalfRect;
        Texture2D gamePadTop;
        SpriteFont font;

        RectangleF[] screenRects;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);

            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 720;

            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            //
            // calculate screen regions
            //
#if WINDOWS
            Rectangle safeRect = new Rectangle(128, 72, 1024, 576); // simulate TitleSafeRegion on windows :-)
#else
            Rectangle safeRect = GraphicsDevice.Viewport.TitleSafeArea;
#endif
            float width = safeRect.Width * 0.5f;
            float height = safeRect.Height * 0.5f;
            screenRects = new RectangleF[4];
            screenRects[0] = new RectangleF(0.0f, 0.0f, width, height); screenRects[0].TopLeft += new Vector2(safeRect.Left, safeRect.Top);
            screenRects[1] = new RectangleF(width, 0.0f, width, height); screenRects[1].TopLeft += new Vector2(safeRect.Left, safeRect.Top);
            screenRects[2] = new RectangleF(0.0f, height, width, height); screenRects[2].TopLeft += new Vector2(safeRect.Left, safeRect.Top);
            screenRects[3] = new RectangleF(width, height, width, height); screenRects[3].TopLeft += new Vector2(safeRect.Left, safeRect.Top);

            //
            // create the InputManager
            //
            inputManager = new starLiGHT.Input.InputManager(this);
            Components.Add(inputManager);

            TriggerAction ta;
            AnalogAxisAction aaa;

#if WINDOWS
            ta = inputManager.createAction("MOUSE_LEFT", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(MouseButtons.LeftButton, LogicalPlayerIndex.One));
            ta = inputManager.createAction("MOUSE_MIDDLE", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(MouseButtons.MiddleButton, LogicalPlayerIndex.One));
            ta = inputManager.createAction("MOUSE_RIGHT", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(MouseButtons.RightButton, LogicalPlayerIndex.One));

            aaa = inputManager.createAction("MOUSE_POSITION", typeof(AnalogAxisAction)) as AnalogAxisAction;
            aaa.AddPositionalControl(inputManager.GetInputDevice(MouseAxis.POSITION, LogicalPlayerIndex.One));

            aaa = inputManager.createAction("MOUSE_WHEEL", typeof(AnalogAxisAction)) as AnalogAxisAction;
            aaa.AddPositionalControl(inputManager.GetInputDevice(MouseAxis.WHEEL, LogicalPlayerIndex.One));
#endif

#if WINDOWS || XBOX
            ta = inputManager.createAction("EXIT", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.Escape, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.Back, LogicalPlayerIndex.One));

            for (int i = 0; i < 4; i++)
            {
                LogicalPlayerIndex logicalPlayer = (LogicalPlayerIndex)i;

                aaa = inputManager.createAction("LEFT_THUMBSTICK", typeof(AnalogAxisAction), logicalPlayer) as AnalogAxisAction;
                aaa.AddPositionalControl(inputManager.GetInputDevice(GamePadAxis.LEFT_STICK, logicalPlayer));
                aaa = inputManager.createAction("RIGHT_THUMBSTICK", typeof(AnalogAxisAction), logicalPlayer) as AnalogAxisAction;
                aaa.AddPositionalControl(inputManager.GetInputDevice(GamePadAxis.RIGHT_STICK, logicalPlayer));
                aaa = inputManager.createAction("LEFT_TRIGGER", typeof(AnalogAxisAction), logicalPlayer) as AnalogAxisAction;
                aaa.AddPositionalControl(inputManager.GetInputDevice(GamePadAxis.LEFT_TRIGGER, logicalPlayer));
                aaa = inputManager.createAction("RIGHT_TRIGGER", typeof(AnalogAxisAction), logicalPlayer) as AnalogAxisAction;
                aaa.AddPositionalControl(inputManager.GetInputDevice(GamePadAxis.RIGHT_TRIGGER, logicalPlayer));

                ta = inputManager.createAction("PAD_A", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.A, logicalPlayer));
                ta = inputManager.createAction("PAD_B", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.B, logicalPlayer));
                ta = inputManager.createAction("PAD_X", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.X, logicalPlayer));
                ta = inputManager.createAction("PAD_Y", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.Y, logicalPlayer));
                ta = inputManager.createAction("PAD_TOP", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.DPadUp, logicalPlayer));
                ta.AddDigitalControl(new PositionalToDigitalAdapter(inputManager.GetInputDevice(GamePadAxis.LEFT_STICK, LogicalPlayerIndex.One), PositionalDirection.UP, 0.5f));
                ta = inputManager.createAction("PAD_DOWN", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.DPadDown, logicalPlayer));
                ta.AddDigitalControl(new PositionalToDigitalAdapter(inputManager.GetInputDevice(GamePadAxis.LEFT_STICK, LogicalPlayerIndex.One), PositionalDirection.DOWN, 0.5f));
                ta = inputManager.createAction("PAD_LEFT", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.DPadLeft, logicalPlayer));
                ta.AddDigitalControl(new PositionalToDigitalAdapter(inputManager.GetInputDevice(GamePadAxis.LEFT_STICK, LogicalPlayerIndex.One), PositionalDirection.LEFT, 0.5f));
                ta = inputManager.createAction("PAD_RIGHT", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.DPadRight, logicalPlayer));
                ta.AddDigitalControl(new PositionalToDigitalAdapter(inputManager.GetInputDevice(GamePadAxis.LEFT_STICK, LogicalPlayerIndex.One), PositionalDirection.RIGHT, 0.5f));
                ta = inputManager.createAction("PAD_START", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.Start, logicalPlayer));
                ta = inputManager.createAction("PAD_BACK", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.Back, logicalPlayer));
                ta = inputManager.createAction("PAD_LSTICK", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.LeftStick, logicalPlayer));
                ta = inputManager.createAction("PAD_RSTICK", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.RightStick, logicalPlayer));
                ta = inputManager.createAction("PAD_LSHOULDER", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.LeftShoulder, logicalPlayer));
                ta = inputManager.createAction("PAD_RSHOULDER", typeof(TriggerAction), logicalPlayer) as TriggerAction;
                ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.RightShoulder, logicalPlayer));
            }
#endif

            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            mouseTexture = Content.Load<Texture2D>(@"Mouse/Mouse");
            buttonTexture = Content.Load<Texture2D>(@"Mouse/ButtonPress");
            
            gamePadFront = Content.Load<Texture2D>(@"GamePad/con_front_ortho");
            gamePadFrontHalfRect = new RectangleF(0, 0, gamePadFront.Width * 0.5f, gamePadFront.Height * 0.5f);

            gamePadTop = Content.Load<Texture2D>(@"GamePad/con_top_ortho");
            font = Content.Load<SpriteFont>(@"SpriteFont1");
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (inputManager.IsActionRelease("EXIT"))
                this.Exit();

            StringBuilder devices = new StringBuilder();
            devices.AppendLine("Available devices:");
            foreach (IControlDevice device in inputManager.InputDevices)
            {
                devices.AppendLine(String.Format("{0} (connected: {1} player index: {2})", device.DeviceType, device.IsConnected, device.PlayerIndex));
            }
            deviceDebug = devices.ToString();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();

#if WINDOWS
            Vector2 pos = inputManager.ActionPosition("MOUSE_POSITION");
            Vector2 wheel = inputManager.ActionPosition("MOUSE_WHEEL");

            spriteBatch.Draw(mouseTexture, pos + new Vector2(0, 0), Color.White);

            if (inputManager.IsActionHeld("MOUSE_LEFT"))
                spriteBatch.Draw(buttonTexture, pos + new Vector2(0, 0), Color.White);

            if (inputManager.IsActionHeld("MOUSE_MIDDLE"))
                spriteBatch.Draw(buttonTexture, pos + new Vector2(30, 0), Color.White);

            if (inputManager.IsActionHeld("MOUSE_RIGHT"))
                spriteBatch.Draw(buttonTexture, pos + new Vector2(60, 0), Color.White);
#endif

#if WINDOWS || XBOX
            GamepadDevice pad;
            Color tint;

            for (int i = 0; i < 4; i++)
            {
                pad = inputManager.GetInputDevice(LogicalPlayer.GetPlayerIndex((LogicalPlayerIndex)i), starLiGHT.Input.DeviceType.GAMEPAD) as GamepadDevice;

                if (pad != null)
                {
                    if (!pad.IsConnected)
                    {
                        tint = new Color(1.0f, 0.0f, 0.0f, 0.5f);
                    }
                    else
                    {
                        tint = Color.White;
                    }

                    spriteBatch.Draw(gamePadFront, screenRects[i].TopLeft, null, tint, 0.0f, Vector2.Zero, 0.5f, SpriteEffects.None, 1.0f);

                    if (pad.IsConnected)
                    {
                        LogicalPlayerIndex logicalPlayer = (LogicalPlayerIndex)i;

                        if (inputManager.IsActionHeld("PAD_A", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(177.0f, 98.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_B", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(195.0f, 79.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_X", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(159.0f, 79.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_Y", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(177.0f, 61.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_LEFT", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(55.0f, 120.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_RIGHT", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(88.0f, 120.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_TOP", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(72.0f, 105.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_DOWN", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(72.0f, 135.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_START", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(133.0f, 81.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_BACK", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(83.0f, 81.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_LSTICK", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(40.0f, 79.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_RSTICK", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(141.0f, 120.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_LSHOULDER", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(40.0f, 40.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        if (inputManager.IsActionHeld("PAD_RSHOULDER", logicalPlayer))
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(177.0f, 40.0f), new Color(1.0f, 1.0f, 1.0f, 0.50f));

                        Vector2 position = inputManager.ActionPosition("LEFT_THUMBSTICK", logicalPlayer);
                        if (position != Vector2.Zero)
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(40.0f, 79.0f) + (position * 15.0f * new Vector2(1.0f, -1.0f)), new Color(0.0f, 1.0f, 0.0f, 0.50f));

                        position = inputManager.ActionPosition("RIGHT_THUMBSTICK", logicalPlayer);
                        if (position != Vector2.Zero)
                            spriteBatch.Draw(buttonTexture, screenRects[i].TopLeft + new Vector2(141.0f, 120.0f) + (position * 15.0f * new Vector2(1.0f, -1.0f)), new Color(0.0f, 1.0f, 0.0f, 0.50f));
                    
                    }
                }
            }
#endif

            spriteBatch.DrawString(font, deviceDebug, new Vector2(380, 300), Color.White);

            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
